package com.dony.order.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.dony.common.utils.SecurityUtils;
import com.dony.common.utils.StringUtils;
import com.dony.common.utils.bean.BeanUtils;
import com.dony.common.utils.file.OssUtils;
import com.dony.common.utils.file.PdfUtils;
import com.dony.common.utils.price.ExchangeRateUtils;
import com.dony.order.domain.OperationRecord;
import com.dony.order.domain.Order;
import com.dony.order.domain.vo.OrderPackVo;
import com.dony.order.mapper.OrderMapper;
import com.dony.order.service.ILogisticsService;
import com.dony.order.service.IOrderPackService;
import com.dony.shop.domain.enums.ShopeeCountryEnum;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;


/**
 * 订单Service业务层处理
 *
 * @author dony
 * @date 2022-09-07
 */
@Slf4j
@Service("orderPackService")
public class OrderPackServiceImpl extends MPJBaseServiceImpl<OrderMapper, Order> implements IOrderPackService {

    @Resource
    private ExchangeRateUtils rateUtils;
    @Resource
    private ILogisticsService logisticsService;
    @Resource
    OssUtils ossUtils;
    @Resource
    ThreadPoolTaskExecutor executor;

    @Override
    public List<Order> listByParam(OrderPackVo order) {
        //查询待打包的订单
        MPJLambdaWrapper<Order> wrapper = new MPJLambdaWrapper<>();
        wrapper.selectAll(Order.class).selectAll(OperationRecord.class).selectCollection(OperationRecord.class, Order::getRecords)
                .leftJoin(OperationRecord.class, OperationRecord::getOrderSn, Order::getOrderSn);
        //精确查询
        if (order.getMerchantId() != null) {
            wrapper.eq(Order::getMerchantId, order.getMerchantId());
        }
        if (order.getShopId() != null) {
            wrapper.eq(Order::getShopId, order.getShopId());
        }
        //通过订单号查询
        if (StringUtils.isNotEmpty(order.getOrderSn())) {
            wrapper.eq(Order::getOrderSn, order.getOrderSn().toUpperCase());
            //默认按创建时间排序
            wrapper.orderByDesc(Order::getCreateTime);
            wrapper.eq(Order::getTenantId, SecurityUtils.getDeptId());
            return selectJoinList(Order.class, wrapper);
        }
        if (StringUtils.isNotEmpty(order.getBuyerUsername())) {
            wrapper.eq(Order::getBuyerUsername, order.getBuyerUsername());
            //默认按创建时间排序
            wrapper.orderByDesc(Order::getCreateTime);
            wrapper.eq(Order::getTenantId, SecurityUtils.getDeptId());
            return selectJoinList(Order.class, wrapper);
        }
        if (StringUtils.isNotEmpty(order.getRegion())) {
            wrapper.eq(Order::getRegion, order.getRegion());
        }
        if (StringUtils.isNotEmpty(order.getOrderStatus())) {
            wrapper.eq(Order::getOrderStatus, order.getOrderStatus());
        }
        //排序查询条件
        if (order.getSort() != null) {
            switch (order.getSort()) {
                case "ship_by_date":
                    wrapper.orderByAsc(Order::getShipByDate);
                    break;
                case "create_time":
                    wrapper.orderByAsc(Order::getCreateTime);
                    break;
                case "pay_time":
                    wrapper.orderByAsc(Order::getPayTime);
                    break;
            }
        }
        if (order.getSysStatus() != null) {
            //优先加急
            wrapper.orderByDesc(Order::getEmergency);
            //处理超期的订单
            switch (order.getSysStatus()) {
                case 0:
                    wrapper.gt(Order::getShipByDate, LocalDateTime.now().plus(-30, ChronoUnit.DAYS));
                    wrapper.lt(Order::getShipByDate, LocalDateTime.now().plus(1, ChronoUnit.DAYS));
                    wrapper.in(Order::getOrderStatus, "READY_TO_SHIP", "RETRY_SHIP", "IN_CANCEL", "PROCESSED");
                    wrapper.notIn(Order::getSysStatus, 6);
                    wrapper.orderByAsc(Order::getShipByDate);
                    break;
                case 2:
                    wrapper.orderByAsc(Order::getShipByDate);
                    wrapper.eq(Order::getSysStatus, order.getSysStatus());
                    break;
                case 3:
                    wrapper.orderByDesc(Order::getOperationTime);
                    wrapper.eq(Order::getSysStatus, order.getSysStatus());
                    break;
                default:
                    wrapper.eq(Order::getSysStatus, order.getSysStatus());
                    break;
            }
        }
        //默认按创建时间排序
        wrapper.orderByDesc(Order::getCreateTime);
        wrapper.eq(Order::getTenantId, SecurityUtils.getDeptId());
        return selectJoinList(Order.class, wrapper);
    }

    @Override
    public List<OrderPackVo> handleOrderList(List<Order> orders) {
        return orders.stream().map(o -> {
            //封装页面的展示对象
            OrderPackVo packVo = new OrderPackVo();
            BeanUtils.copyProperties(o, packVo);
            //封装链接头部
            //packVo.setUri(ShopeeCountryEnum.getUrlByCapital(o.getRegion()) + "/product/" + o.getShopId());
            //计算人民币价格
            if (o.getIncome() != null) {
                //优先设置收入价格，如果为空则用income
                packVo.setTotalAmount(rateUtils.getRMBPrice(o.getCurrency(), o.getIncome()));
            } else if (o.getTotalAmount() != null) {
                packVo.setTotalAmount(rateUtils.getRMBPrice(o.getCurrency(), o.getTotalAmount()));
            }
            //封装国家
            //ackVo.setRegion(ShopeeCountryEnum.getNameByCapital(o.getRegion()));
            //TODO 获取商家信息
            packVo.setItemList(JSON.parseArray(o.getItemList()));
            return packVo;
        }).collect(Collectors.toList());
    }


    @Override
    public String printOrder(String[] orderSns) {
        if (orderSns.length == 1) {
            //查询是否有内容
            String orderSn = orderSns[0];
            Order order = this.getById(orderSn);
            if (StringUtils.isNotEmpty(order.getDocUrl())) {
                return order.getDocUrl();
            }
            //创建面单
            List<String> snList = Arrays.asList(orderSns);
            logisticsService.createShippingDocument(snList);
            if (!logisticsService.tryGetShippingDocumentResult(snList, 3)) {
                return null;
            }
            byte[] bytes = logisticsService.downloadShippingDocument(order.getShopId(), orderSn);
            if (bytes == null) {
                return null;
            }
            String path = "order-pdf/" + orderSn.substring(0, 2) + "/" + orderSn.substring(2, 4) + "/" + orderSn + ".pdf";
            if (ossUtils.uploadFile(path, bytes)) {
                String docUrl = "https://shopee-document.oss-cn-shenzhen.aliyuncs.com/" + path;
                LambdaUpdateWrapper<Order> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                lambdaUpdateWrapper.eq(Order::getOrderSn, orderSn).set(Order::getDocUrl, docUrl);
                this.update(lambdaUpdateWrapper);
                return docUrl;
            }
            return null;
        }
        //多个订单
        List<String> snList = Arrays.asList(orderSns);
        logisticsService.createShippingDocument(snList);
        if (!logisticsService.tryGetShippingDocumentResult(snList, 3)) {
            return null;
        }
        //开始合成文件
        List<byte[]> pdfs = new ArrayList<>();
        try {
            List<CompletableFuture<byte[]>> futures = snList.stream()
                    .map(orderSn -> CompletableFuture.supplyAsync(() -> {
                        Order order = this.getById(orderSn);
                        byte[] bytes = logisticsService.downloadShippingDocument(order.getShopId(), orderSn);
                        if (bytes == null) {
                            return null;
                        }
                        //如果没有保存过
                        if (StringUtils.isEmpty(order.getDocUrl())) {
                            //异步执行保存
                            executor.execute(() -> {
                                String path = "order-pdf/" + orderSn.substring(0, 2) + "/" + orderSn.substring(2, 4) + "/" + orderSn + ".pdf";
                                if (ossUtils.uploadFile(path, bytes)) {
                                    String docUrl = "https://shopee-document.oss-cn-shenzhen.aliyuncs.com/" + path;
                                    LambdaUpdateWrapper<Order> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                                    lambdaUpdateWrapper.eq(Order::getOrderSn, orderSn).set(Order::getDocUrl, docUrl);
                                    this.update(lambdaUpdateWrapper);
                                }
                            });
                        }
                        return bytes;
                    }, executor)).collect(Collectors.toList());
            CompletableFuture<Void> allOf = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
            allOf.join(); // 等待所有任务完成
            if (futures.stream().anyMatch(future -> future.join() == null)) {
                log.error("有下载任务失败，导致整体失败！");
                return null;
            }
            pdfs = futures.stream().map(CompletableFuture::join).collect(Collectors.toList());
        } catch (Exception e) {
            log.error("整体下载失败！{}", e);
            return null;
        }
        try {
            byte[] mergeMultiplePdfs = PdfUtils.mergeMultiplePdfs(pdfs);
            String path = "order-pdf/temp/" + orderSns[0].substring(0, 2) + "/" + orderSns[0].substring(2, 4) + "/" + String.join("-", snList) + ".pdf";
            if (!ossUtils.uploadFile(path, mergeMultiplePdfs)) {
                return null;
            }
            String docUrl = "https://shopee-document.oss-cn-shenzhen.aliyuncs.com/" + path;
            return docUrl;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<Order> getInCancelOrder() {
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.in("order_status", "IN_CANCEL", "TO_RETURN");
        wrapper.orderByAsc("order_status");
        wrapper.eq("tenant_id", SecurityUtils.getDeptId());
        return this.list(wrapper);
    }

}
